home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / WINDOWS / MWPROPVW.ARJ / PROPVIEW.C < prev    next >
C/C++ Source or Header  |  1992-01-27  |  47KB  |  2,255 lines

  1. /*****************************************************************************
  2.  
  3.   PROGRAM    : PropView (c) 1991 All rights reserved
  4.   AUTHOR    : Mike Klein
  5.   VERSION    : 1.5
  6.   FILE    : propview.exe
  7.   FINISHED  : 07-08-91
  8.  
  9.   REQUIREMENTS: Windows 3.x
  10.  
  11.   PURPOSE    : Point to any window on screen and view info/properties, and
  12.                   send messages to window too.
  13.  
  14. *****************************************************************************/
  15.  
  16.  
  17. #define NOCOMM                                            
  18.  
  19. #include <windows.h>
  20. #include <direct.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24.  
  25. #include "propview.h"
  26.  
  27. static HWND    hDlgPropView;
  28. static HANDLE  hInstPropView;
  29. #ifdef PROPVIEW
  30. extern HWND    hMain;
  31. HWND    hDlgActive;
  32. #else
  33. static HWND    hDlgActive;
  34. #endif
  35. static HWND    hWndTarget;
  36. static HWND   hDlgChildren;
  37. static HWND   hDlgProperties;
  38. static HWND   hDlgSendMsg;
  39. static HWND   hDlgExtraData;
  40. static HWND   hDlgStyles;
  41.  
  42. static BYTE Text[100];
  43.  
  44. static BOOL Capturing = FALSE;
  45.  
  46. static FARPROC lpEnumWindowPropsProc;
  47. static FARPROC lpEnumChildrenProc;
  48.  
  49. static BOOL ShowHex      = TRUE;
  50. static BOOL ShowScreenCoord  = TRUE;
  51.  
  52.  
  53. //
  54. // Some internally used functions
  55. //
  56.  
  57. VOID PASCAL ExamineWindow(HWND);
  58. VOID PASCAL DrawIcons(VOID);
  59. VOID PASCAL OutlineWindow(HWND);
  60. VOID PASCAL UpdatePos(VOID);
  61.  
  62.  
  63. /*
  64.   Some specific differences between the MEWEL and Windows implementations
  65. */
  66. #if defined(MEWEL)
  67. PSTR pszMsgFile = "wmmewel.msg";
  68. #else
  69. PSTR pszMsgFile = "wm.msg";
  70. #endif
  71.  
  72.  
  73. /*****************************************************************************
  74.  
  75.     FUNCTION: WinMain
  76.  
  77.     PURPOSE : Calls initialization function, processes message loop
  78.  
  79. *****************************************************************************/
  80.  
  81. #if defined(PROPVIEW)
  82. int PASCAL PVWinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
  83.   int nCmdShow)
  84. #else
  85. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
  86.   int nCmdShow)
  87. #endif
  88. {
  89.   WNDCLASS  wc;
  90.   MSG      msg;
  91.  
  92.   int ChildTabs[3];
  93.   int PropTab;
  94.  
  95.   int      hFile;
  96.   BYTE    Msg[81];
  97.   BYTE    Hex[5];
  98.   OFSTRUCT  OFstruct;
  99.  
  100.   //
  101.   // See if a version of Propview is already running
  102.   //
  103.  
  104.   if(!hPrevInstance)
  105.   {
  106.     hInstPropView = hInstance;
  107.  
  108.     //
  109.     // Fill in window class structure with parameters that describe the
  110.     // main window.
  111.     //
  112.  
  113.     wc.lpszClassName = (LPSTR) "PropView";
  114.     wc.lpfnWndProc   = PVWndProc;
  115.     wc.hInstance     = hInstPropView;
  116.     wc.lpszMenuName  = (LPSTR) "PropView";
  117.     wc.style         = CS_DBLCLKS;
  118.     wc.hIcon         = LoadIcon(hInstance, "PropView");
  119.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  120.     wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  121.     wc.cbClsExtra    = 0;
  122.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  123.  
  124.     if(!RegisterClass((LPWNDCLASS) &wc))
  125.     {
  126.       return(FALSE);
  127.     }
  128.  
  129.     //
  130.     // Fill in window class structure with parameters that describe the
  131.     // single-listbox window.
  132.     //
  133.  
  134.     wc.lpszClassName = (LPSTR) "SingleViewer";
  135.     wc.lpfnWndProc   = GenericViewerWndProc;
  136.     wc.hInstance     = hInstPropView;
  137.     wc.lpszMenuName  = NULL;
  138.     wc.style         = CS_DBLCLKS;
  139.     wc.hIcon         = LoadIcon(hInstance, "PropView");
  140.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  141.     wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  142.     wc.cbClsExtra    = 0;
  143.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  144.  
  145.     if(!RegisterClass((LPWNDCLASS) &wc))
  146.     {
  147.       return(FALSE);
  148.     }
  149.  
  150.     //
  151.     // Fill in window class structure with parameters that describe the
  152.     // double-listbox window.
  153.     //
  154.  
  155.     wc.lpszClassName = (LPSTR) "DoubleViewer";
  156.     wc.lpfnWndProc   = GenericViewerWndProc;
  157.     wc.hInstance     = hInstPropView;
  158.     wc.lpszMenuName  = NULL;
  159.     wc.style         = CS_DBLCLKS;
  160.     wc.hIcon         = LoadIcon(hInstance, "PropView");
  161.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  162.     wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  163.     wc.cbClsExtra    = 0;
  164.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  165.  
  166.     if(!RegisterClass((LPWNDCLASS) &wc))
  167.     {
  168.       return(FALSE);
  169.     }
  170.  
  171.     //
  172.     // Fill in window class structure with parameters that describe the
  173.     // message sending window.
  174.     //
  175.  
  176.     wc.lpszClassName = (LPSTR) "SendMsg";
  177.     wc.lpfnWndProc   = SendMsgWndProc;
  178.     wc.hInstance     = hInstPropView;
  179.     wc.lpszMenuName  = NULL;
  180.     wc.style         = CS_DBLCLKS;
  181.     wc.hIcon         = LoadIcon(hInstance, "PropView");
  182.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  183.     wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  184.     wc.cbClsExtra    = 0;
  185.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  186.  
  187.     if(!RegisterClass((LPWNDCLASS) &wc))
  188.     {
  189.       return(FALSE);
  190.     }
  191.  
  192.     //
  193.     // Create the main window PropView
  194.     //
  195.  
  196.     CreateDialog
  197.     (
  198.       hInstPropView,
  199.       "PropView",
  200. #ifdef PROPVIEW
  201.       hMain,
  202. #else
  203.       NULL,
  204. #endif
  205.       NULL
  206.     );
  207.  
  208.     //
  209.     // Make procedure instances for enum functions
  210.     //
  211.  
  212.     if((lpEnumWindowPropsProc =
  213.       MakeProcInstance(EnumWindowPropsProc, hInstPropView)) == NULL)
  214.     {
  215.       return(FALSE);
  216.     }
  217.  
  218.     if((lpEnumChildrenProc =
  219.       MakeProcInstance(EnumChildrenProc, hInstPropView)) == NULL)
  220.     {
  221.       return(FALSE);
  222.     }
  223.  
  224.     //
  225.     // Create the Children window & set caption
  226.     //
  227.  
  228.     if((hDlgChildren = CreateDialog
  229.     (
  230.       hInstPropView,
  231.       "SingleViewer",
  232.       hDlgPropView,
  233.       0L
  234.     )) == NULL)
  235.     {
  236.       return(FALSE);
  237.     }
  238.  
  239.     SetWindowText(hDlgChildren, (LPSTR) "No Children");
  240.     SetDlgItemText
  241.     (
  242.       hDlgChildren,
  243.       IDC_STATIC,
  244.       (LPSTR) "Class\t\tCtrlID\thWnd\tCaption"
  245.     );
  246.  
  247.     //
  248.     // Create the Properties window & set caption
  249.     //
  250.  
  251.     if((hDlgProperties = CreateDialog
  252.     (
  253.       hInstPropView,
  254.       "SingleViewer",
  255.       hDlgPropView,
  256.       0L
  257.     )) == NULL)
  258.     {
  259.       return(FALSE);
  260.     }
  261.  
  262.     SetWindowText(hDlgProperties, (LPSTR) "No Properties");
  263.     SetDlgItemText(hDlgProperties, IDC_STATIC, (LPSTR) "Property\tValue");
  264.  
  265.     //
  266.     // Set tabs for children and properties list boxes
  267.     //
  268.  
  269. #ifdef MEWEL
  270.     ChildTabs[0] = 13;
  271.     ChildTabs[1] = 20;
  272.     ChildTabs[2] = 27;
  273. #else
  274.     ChildTabs[0] = 53;
  275.     ChildTabs[1] = 82;
  276.     ChildTabs[2] = 111;
  277. #endif
  278.  
  279.     SendDlgItemMessage
  280.     (
  281.       hDlgChildren,
  282.       IDC_LISTBOX,
  283.       LB_SETTABSTOPS,
  284.       3,
  285.       (LONG) (LPINT) &ChildTabs
  286.     );
  287.  
  288. #ifdef MEWEL
  289.     PropTab = 12;
  290. #else
  291.     PropTab = 50;
  292. #endif
  293.  
  294.     SendDlgItemMessage
  295.     (
  296.       hDlgProperties,
  297.       IDC_LISTBOX,
  298.       LB_SETTABSTOPS,
  299.       1,
  300.       (LONG) (LPINT) &PropTab
  301.     );
  302.  
  303.     //
  304.     // Create the Data window
  305.     //
  306.  
  307.     if((hDlgExtraData = CreateDialog
  308.     (
  309.       hInstPropView,
  310.       "DoubleViewer",
  311.       hDlgPropView,
  312.       0L
  313.     )) == NULL)
  314.     {
  315.       return(FALSE);
  316.     }
  317.  
  318.     SetWindowText(hDlgExtraData, (LPSTR) "Extra Data");
  319.  
  320.     //
  321.     // Create the Styles window
  322.     //
  323.  
  324.     if((hDlgStyles = CreateDialog
  325.     (
  326.       hInstPropView,
  327.       "DoubleViewer",
  328.       hDlgPropView,
  329.       0L
  330.     )) == NULL)
  331.     {
  332.       return(FALSE);
  333.     }
  334.  
  335.     SetWindowText(hDlgStyles, (LPSTR) "Styles");
  336.  
  337.     //
  338.     // Create the SendMsg window
  339.     //
  340.  
  341.     if((hDlgSendMsg = CreateDialog
  342.     (
  343.       hInstPropView,
  344.       "SendMsg",
  345.       hDlgPropView,
  346.       0L
  347.     )) == NULL)
  348.     {
  349.       return(FALSE);
  350.     }
  351.  
  352.     //
  353.     // Fill the msgs combobox in SendMsg dialog
  354.     //
  355.  
  356.     hFile = OpenFile((LPSTR) pszMsgFile, (LPOFSTRUCT) &OFstruct, OF_READ);
  357.  
  358.     if(hFile != -1)
  359.     {
  360.       FILE *fp = fdopen(hFile, "r");
  361.  
  362.       while(fscanf(fp,"%22s%4s", Msg, Hex) != EOF )
  363.       {
  364.         if(Msg[0] != 'W')
  365.         {
  366.           break;
  367.         }
  368.  
  369.         wsprintf((LPSTR) Text, "%-35.35s %s", (LPSTR) &Msg[3], (LPSTR) Hex);
  370.  
  371.         SendDlgItemMessage
  372.         (
  373.           hDlgSendMsg,
  374.           IDC_MESSAGES,
  375.           CB_ADDSTRING,
  376.           0,
  377.           (LONG) (LPSTR) Text
  378.         );
  379.       }
  380.  
  381.       fclose(fp);
  382.     }
  383.  
  384.     //
  385.     // Check some radiobutton defaults
  386.     //
  387.  
  388.     CheckRadioButton(hDlgPropView, IDC_HEX, IDC_DEC, IDC_HEX);
  389.     CheckRadioButton(hDlgPropView, IDC_SCREEN, IDC_DIALOG, IDC_SCREEN);
  390.   }
  391.   else
  392.   {
  393.     //
  394.     // If there was another instance of PropView running, then switch to
  395.     // it by finding any window of class = "PropView". Then, if it's an
  396.     // icon, open the window, otherwise just make it active.
  397.     //
  398.  
  399.     if(hDlgPropView = FindWindow("PropView", NULL))
  400.     {
  401.       if(IsIconic(hDlgPropView))
  402.       {
  403.         ShowWindow(hDlgPropView, SW_SHOWNORMAL);
  404.       }
  405.  
  406.       SetActiveWindow(hDlgPropView);
  407.     }
  408.     return(FALSE);
  409.   }
  410.  
  411.   //
  412.   // Acquire and dispatch messages until a WM_QUIT message is received.
  413.   // The window handle hDlgActive points to the currently active window,
  414.   // and is used to identify and process keystrokes going to any modeless
  415.   // dialog box.
  416.   //
  417.  
  418. #if defined(PROPVIEW)
  419.   return TRUE;
  420. #else
  421.   while(GetMessage((LPMSG) &msg, NULL, NULL, NULL))
  422.   {
  423.     if(hDlgActive != NULL)
  424.     {
  425.       if(!IsDialogMessage(hDlgActive, (LPMSG) &msg))
  426.       {
  427.         TranslateMessage((LPMSG) &msg);
  428.         DispatchMessage((LPMSG) &msg);
  429.       }
  430.     }
  431.     else
  432.     {
  433.       TranslateMessage((LPMSG) &msg);
  434.       DispatchMessage((LPMSG) &msg);
  435.     }
  436.   }
  437.  
  438.   FreeProcInstance(lpEnumWindowPropsProc);
  439.   FreeProcInstance(lpEnumChildrenProc);
  440. #endif
  441. }
  442.  
  443.  
  444. /*****************************************************************************
  445.  
  446.     FUNCTION: PVWndProc
  447.  
  448.     PURPOSE : Processes messages for PropView dialog box
  449.  
  450. *****************************************************************************/
  451.  
  452. LONG FAR PASCAL PVWndProc(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam)
  453. {
  454.   HWND  hWndTemp;
  455.   POINT  Point;
  456.  
  457.   FARPROC lpProc;
  458.  
  459.   //
  460.   // Switch stmt for acting on msgs
  461.   //
  462.  
  463.   switch(wMsg)
  464.   {
  465.     case WM_CREATE :
  466.  
  467.       hDlgPropView = hWnd;
  468.       break;
  469.  
  470.     case WM_MOUSEMOVE :
  471.  
  472.       //
  473.       // Check to see if we're capturing or not
  474.       //
  475.  
  476.       if(!Capturing)
  477.       {
  478.         return(DefDlgProc(hWnd, wMsg, wParam, lParam));
  479.       }
  480.  
  481.       //
  482.       // Find out the window to query. Abort if same as last hWnd
  483.       //
  484.  
  485.       GetCursorPos((LPPOINT) &Point);
  486.  
  487.       if((hWndTemp = WindowFromPoint(Point)) == NULL)
  488.       {
  489.         break;
  490.       }
  491.  
  492.       //
  493.       // Screen out if same window
  494.       //
  495.  
  496.       if
  497.       (
  498.         (hWndTemp != hWndTarget) &&
  499.         (hWndTemp != hDlgPropView) &&
  500.         (GetParent(hWndTemp) != hDlgPropView)
  501.       )
  502.       {
  503.         ExamineWindow(hWndTemp);
  504.       }
  505.  
  506.       UpdatePos();
  507.       break;
  508.  
  509.     case WM_LBUTTONDOWN :
  510.     case WM_MBUTTONDOWN :
  511.     case WM_RBUTTONDOWN :
  512.  
  513.       //
  514.       // Any mouse button press cancels capture mode
  515.       //
  516.  
  517.       if(Capturing)
  518.       {
  519.         Capturing = FALSE;
  520.         ReleaseCapture();
  521.       }
  522.  
  523.       break;
  524.  
  525.     case WM_COMMAND :
  526.  
  527.       switch(wParam)
  528.       {
  529.         case IDOK     :
  530.         case IDCANCEL :
  531.  
  532.           SendMessage(hWnd, WM_CLOSE, 0, 0L);
  533.           break;
  534.  
  535.         case IDC_HEX :
  536.  
  537.           ShowHex = TRUE;
  538.           ExamineWindow(hWndTarget);
  539.           UpdatePos();
  540.           return(0L);
  541.  
  542.         case IDC_DEC :
  543.  
  544.           ShowHex = FALSE;
  545.           ExamineWindow(hWndTarget);
  546.           UpdatePos();
  547.           return(0L);
  548.  
  549.         case IDC_SCREEN :
  550.  
  551.           ShowScreenCoord = TRUE;
  552.           ExamineWindow(hWndTarget);
  553.           UpdatePos();
  554.           return(0L);
  555.  
  556.         case IDC_DIALOG :
  557.  
  558.           ShowScreenCoord = FALSE;
  559.           ExamineWindow(hWndTarget);
  560.           UpdatePos();
  561.           return(0L);
  562.  
  563.         case IDC_SPY :
  564.  
  565.           //
  566.           // Run a copy of Spy
  567.           //
  568.  
  569. #if defined(MEWEL)
  570.           MessageBox(NULL, "There is no SPY for MEWEL yet.", "Spy",
  571.                      MB_OK | MB_ICONEXCLAMATION);
  572. #else
  573.           WinExec("spy", SW_SHOWNORMAL);
  574. #endif
  575.           return(0L);
  576.  
  577.         case IDC_CHILDREN :
  578.  
  579.           //
  580.           // Show/hide the "children" window
  581.           //
  582.  
  583.           if(IsWindowVisible(hDlgChildren))
  584.           {
  585.             ShowWindow(hDlgChildren, SW_HIDE);
  586.           }
  587.           else
  588.           {
  589.             ShowWindow(hDlgChildren, SW_SHOWNORMAL);
  590.           }
  591.           return(0L);
  592.  
  593.         case IDC_SENDMSG :
  594.  
  595.           //
  596.           // Show/hide the "SendMsg" dialog
  597.           //
  598.  
  599.           if(IsWindowVisible(hDlgSendMsg))
  600.           {
  601.             ShowWindow(hDlgSendMsg, SW_HIDE);
  602.           }
  603.           else
  604.           {
  605.             ShowWindow(hDlgSendMsg, SW_SHOWNORMAL);
  606.           }
  607.           return(0L);
  608.  
  609.         case IDC_DATA :
  610.  
  611.           //
  612.           // Show/hide the window/class data dialog
  613.           //
  614.  
  615.           if(IsWindowVisible(hDlgExtraData))
  616.           {
  617.             ShowWindow(hDlgExtraData, SW_HIDE);
  618.           }
  619.           else
  620.           {
  621.             ShowWindow(hDlgExtraData, SW_SHOWNORMAL);
  622.           }
  623.           return(0L);
  624.  
  625.         case IDC_STYLES :
  626.  
  627.           //
  628.           // Show/hide the window/class data dialog
  629.           //
  630.  
  631.           if(IsWindowVisible(hDlgStyles))
  632.           {
  633.             ShowWindow(hDlgStyles, SW_HIDE);
  634.           }
  635.           else
  636.           {
  637.             ShowWindow(hDlgStyles, SW_SHOWNORMAL);
  638.           }
  639.           return(0L);
  640.  
  641.         case IDC_PROPERTIES :
  642.  
  643.           //
  644.           // Show/hide the window properties dialog
  645.           //
  646.  
  647.           if(IsWindowVisible(hDlgProperties))
  648.           {
  649.             ShowWindow(hDlgProperties, SW_HIDE);
  650.           }
  651.           else
  652.           {
  653.             ShowWindow(hDlgProperties, SW_SHOWNORMAL);
  654.           }
  655.           return(0L);
  656.  
  657.         case IDM_ABOUT :
  658.  
  659.           //
  660.           // Bring up the modal About dialog box
  661.           //
  662.  
  663.           lpProc = MakeProcInstance(About, hInstPropView);
  664.           DialogBox(hInstPropView, "About", hWnd, lpProc);
  665.           FreeProcInstance(lpProc);
  666.           return(0L);
  667.  
  668.         case IDM_EXIT :
  669.  
  670.           SendMessage(hWnd, WM_CLOSE, 0, 0L);
  671.           return(0L);
  672.  
  673.         case IDM_GO :
  674.  
  675.           Capturing = TRUE;
  676.           SetCapture(hWnd);
  677.           return(0L);
  678.  
  679.         default :
  680.  
  681.           break;
  682.       }
  683.  
  684.       break;
  685.  
  686.     case WM_PAINT :
  687.  
  688.       if(hWndTarget != NULL)
  689.       {
  690.         DrawIcons();
  691.  
  692.         //
  693.         // Validate areas we just painted so WM_PAINT doesn't
  694.         //
  695.  
  696.         ValidateRect(GetDlgItem(hDlgPropView, IDC_HWNDICON), NULL);
  697.         ValidateRect(GetDlgItem(hDlgPropView, IDC_PARENTICON), NULL);
  698.       }
  699.  
  700.       break;
  701.  
  702.     case WM_CLOSE                :
  703.  
  704.       DestroyWindow(hWnd);
  705.       return(0L);
  706.  
  707.     case WM_ACTIVATE             :
  708.  
  709.       hDlgActive = (wParam == NULL) ? NULL : hWnd;
  710.       break;
  711.  
  712.     case WM_DESTROY              :
  713.  
  714. #if !defined(PROPVIEW)
  715.       PostQuitMessage(0);
  716. #endif
  717.       return(0L);
  718.  
  719.     default                      :
  720.  
  721.       break;
  722.   }
  723.  
  724.   return(DefDlgProc(hWnd, wMsg, wParam, lParam));
  725. }
  726.  
  727.  
  728. /*****************************************************************************
  729.  
  730.     FUNCTION: GenericViewerWndProc
  731.  
  732.     PURPOSE : Processes messages for generic listbox display window
  733.  
  734. *****************************************************************************/
  735.  
  736. LONG FAR PASCAL GenericViewerWndProc(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam)
  737. {
  738.   BYTE Entry[50];
  739.   BYTE *ptr;
  740.   HWND hWndTemp;
  741.  
  742.   int Index;
  743.  
  744.   //
  745.   // Switch stmt for acting on msgs
  746.   //
  747.  
  748.   switch(wMsg)
  749.   {
  750.     case WM_COMMAND :
  751.  
  752.       switch(wParam)
  753.       {
  754.         case IDC_LISTBOX :
  755.  
  756.           if(HIWORD(lParam) == LBN_DBLCLK)
  757.           {
  758.             //
  759.             // Get index of entry in listbox clicked on
  760.             //
  761.  
  762.             if((Index = (int) SendDlgItemMessage
  763.             (
  764.               hWnd,
  765.               IDC_LISTBOX,
  766.               LB_GETCURSEL,
  767.               0,
  768.               0L
  769.             )) == LB_ERR)
  770.             {
  771.               break;
  772.             }
  773.  
  774.             //
  775.             // Get entry text
  776.             //
  777.  
  778.             SendDlgItemMessage
  779.             (
  780.               hWnd,
  781.               IDC_LISTBOX,
  782.               LB_GETTEXT,
  783.               Index,
  784.               (LONG) (LPSTR) Entry
  785.             );
  786.  
  787.             if(hDlgChildren == hWnd)
  788.             {
  789.               if(Entry[0] == '\"')
  790.               {
  791.                 //
  792.                 // This is when parent entry of ".." was
  793.                 // selected
  794.                 //
  795.  
  796.                 ExamineWindow(GetParent(hWndTarget));
  797.               }
  798.               else
  799.               {
  800.                 //
  801.                 // Pull out the hWnd field of the child
  802.                 // window we want to examine.
  803.                 //
  804.  
  805.                 if(ptr = strrchr(Entry, '\t'))
  806.                 {
  807.                   if(*(ptr + 1) == '\"')
  808.                   {
  809.                     while(--ptr)
  810.                     {
  811.                       if(*ptr == '\t')
  812.                       {
  813.                         break;
  814.                       }
  815.                     }
  816.                   }
  817.                   else
  818.                   {
  819.                     ++ptr;
  820.                   }
  821.  
  822.                   if(ShowHex)
  823.                   {
  824.                     sscanf(ptr, "%x", &hWndTemp);
  825.                   }
  826.                   else
  827.                   {
  828.                     sscanf(ptr, "%d", &hWndTemp);
  829.                   }
  830.  
  831.                   ExamineWindow(hWndTemp);
  832.                 }
  833.               }
  834.             }
  835.           }
  836.  
  837.           return(0L);
  838.  
  839.         default :
  840.  
  841.           break;
  842.       }
  843.  
  844.       break;
  845.  
  846.     case WM_CLOSE :
  847.  
  848.       if(IsWindowVisible(hWnd))
  849.       {
  850.         ShowWindow(hWnd, SW_HIDE);
  851.       }
  852.       else
  853.       {
  854.         ShowWindow(hWnd, SW_SHOWNORMAL);
  855.       }
  856.       return(0L);
  857.  
  858.     case WM_SIZE :
  859.  
  860. #ifndef MEWEL
  861.       if(wParam != SIZEICONIC)
  862.       {
  863.         if
  864.         (
  865.           hWnd == hDlgChildren ||
  866.           hWnd == hDlgProperties
  867.         )
  868.         {
  869.           //
  870.           // For SingleViewer dialogs...
  871.           //
  872.           // Resize the static text ctrl & list box ctrl so
  873.           // that they fill the size of the resized dialog
  874.           //
  875.  
  876.           if(GetDlgItem(hWnd, IDC_STATIC))
  877.           {
  878.             MoveWindow
  879.             (
  880.               GetDlgItem(hWnd, IDC_STATIC),
  881.               0,
  882.               0,
  883.               LOWORD(lParam),
  884.               12,
  885.               TRUE
  886.             );
  887.           }
  888.  
  889.           if(GetDlgItem(hWnd, IDC_LISTBOX))
  890.           {
  891.             MoveWindow
  892.             (
  893.               GetDlgItem(hWnd, IDC_LISTBOX),
  894.               0,
  895.               12,
  896.               LOWORD(lParam),
  897.               HIWORD(lParam) - 12,
  898.               TRUE
  899.             );
  900.           }
  901.           InvalidateRect(GetDlgItem(hWnd, IDC_STATIC), NULL, TRUE);
  902.         }
  903.         else
  904.         {
  905.           WORD Width  = LOWORD(lParam);
  906.           WORD Height  = HIWORD(lParam);
  907.  
  908.           //
  909.           // For DoubleViewer dialogs...
  910.           //
  911.           // Resize both of the static text ctrls & list box
  912.           // ctrls so that they fill the size of the resized
  913.           // dialog.
  914.           //
  915.  
  916.           if(GetDlgItem(hWnd, IDC_WNDTEXT))
  917.           {
  918.             MoveWindow
  919.             (
  920.               GetDlgItem(hWnd, IDC_WNDTEXT),
  921.               4,
  922.               4,
  923.               Width / 2 - 8,
  924.               12,
  925.               TRUE
  926.             );
  927.           }
  928.  
  929.           if(GetDlgItem(hWnd, IDC_CLSTEXT))
  930.           {
  931.             MoveWindow
  932.             (
  933.               GetDlgItem(hWnd, IDC_CLSTEXT),
  934.               Width / 2 + 2,
  935.               4,
  936.               Width / 2 - 8,
  937.               12,
  938.               TRUE
  939.             );
  940.           }
  941.  
  942.           if(GetDlgItem(hWnd, IDC_WNDLIST))
  943.           {
  944.             MoveWindow
  945.             (
  946.               GetDlgItem(hWnd, IDC_WNDLIST),
  947.               4,
  948.               19,
  949.               Width / 2 - 8,
  950.               Height - (18 + 4),
  951.               TRUE
  952.             );
  953.           }
  954.  
  955.           if(GetDlgItem(hWnd, IDC_CLSLIST))
  956.           {
  957.             MoveWindow
  958.             (
  959.               GetDlgItem(hWnd, IDC_CLSLIST),
  960.               Width / 2 + 2,
  961.               19,
  962.               Width / 2 - 8,
  963.               Height - (18 + 4),
  964.               TRUE
  965.             );
  966.           }
  967.  
  968.           InvalidateRect(GetDlgItem(hWnd, IDC_WNDTEXT), NULL, TRUE);
  969.           InvalidateRect(GetDlgItem(hWnd, IDC_CLSTEXT), NULL, TRUE);
  970.         }
  971.       }
  972. #endif
  973.       break;
  974.  
  975.     case WM_ACTIVATE :
  976.  
  977.       hDlgActive = (wParam == NULL) ? NULL : hWnd;
  978.       break;
  979.  
  980.     default :
  981.       
  982.       break;
  983.   }
  984.  
  985.   return(DefDlgProc(hWnd, wMsg, wParam, lParam));
  986. }
  987.  
  988.  
  989. /*****************************************************************************
  990.  
  991.     FUNCTION: SendMsgWndProc
  992.  
  993.     PURPOSE : Processes messages for message sending dialog
  994.  
  995. *****************************************************************************/
  996.  
  997. LONG FAR PASCAL SendMsgWndProc(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam)
  998. {
  999.   BYTE hWndText[7];
  1000.   BYTE MsgText[50];
  1001.   BYTE Msg[81];
  1002.   BYTE wParamText[5];
  1003.   BYTE lParamText[10];
  1004.  
  1005.   //
  1006.   // Switch stmt for acting on msgs
  1007.   //
  1008.  
  1009.   switch(wMsg)
  1010.   {
  1011.     case WM_COMMAND :
  1012.  
  1013.       switch(wParam)
  1014.       {
  1015.         case IDOK :
  1016.  
  1017.           SendMessage(hWnd, WM_CLOSE, 0, 0L);
  1018.           return(0L);
  1019.  
  1020.         case IDC_SEND :
  1021.  
  1022.           //
  1023.           // Send message to target window
  1024.           //
  1025.  
  1026.           GetDlgItemText
  1027.           (
  1028.             hWnd,
  1029.             IDC_HWNDTOSEND,
  1030.             (LPSTR) hWndText,
  1031.             sizeof(hWndText)
  1032.           );
  1033.           GetDlgItemText
  1034.           (
  1035.             hWnd,
  1036.             IDC_MESSAGES,
  1037.             (LPSTR) MsgText,
  1038.             sizeof(MsgText)
  1039.           );
  1040.           GetDlgItemText
  1041.           (
  1042.             hWnd,
  1043.             IDC_WPARAM,
  1044.             (LPSTR) wParamText,
  1045.             sizeof(wParamText)
  1046.           );
  1047.           GetDlgItemText
  1048.           (
  1049.             hWnd,
  1050.             IDC_LPARAM,
  1051.             (LPSTR) lParamText,
  1052.             sizeof(lParamText)
  1053.           );
  1054.  
  1055.           //
  1056.           // Check for parms not filled in or null window handle
  1057.           //
  1058.  
  1059.           if
  1060.           (
  1061.             hWndText[0] == '\0' ||
  1062.             MsgText[0] == '\0' ||
  1063.             wParamText[0] == '\0' ||
  1064.             lParamText[0] == '\0' ||
  1065.             !IsWindow(hWndTarget)
  1066.           )
  1067.           {
  1068.             return(0L);;
  1069.           }
  1070.  
  1071.           lstrcpy((LPSTR) Msg, (LPSTR) &MsgText[36]);
  1072.  
  1073.           if(ShowHex)
  1074.           {
  1075.             hWnd  = (HWND) strtol(hWndText, NULL, 16);
  1076.             wMsg  = (WORD) strtol(Msg, NULL, 16);
  1077.             wParam  = (WORD) strtol(wParamText, NULL, 16);
  1078.             lParam  = (DWORD) strtol(lParamText, NULL, 16);
  1079.           }
  1080.           else
  1081.           {
  1082.             hWnd  = (HWND) strtol(hWndText, NULL, 10);
  1083.             wMsg  = (WORD) strtol(Msg, NULL, 10);
  1084.             wParam  = (WORD) strtol(wParamText, NULL, 10);
  1085.             lParam  = (DWORD) strtol(lParamText, NULL, 10);
  1086.           }
  1087.  
  1088.           if(PostMessage(hWnd, wMsg, wParam, lParam) == FALSE)
  1089.              {
  1090.               MessageBeep(0);
  1091.                MessageBox
  1092.             (
  1093.               hDlgSendMsg,
  1094.               "PostMessage() failed",
  1095.               "ERROR",
  1096.               MB_ICONEXCLAMATION | MB_OK
  1097.             );
  1098.           }
  1099.  
  1100.           SetActiveWindow(hDlgSendMsg);
  1101.           return(0L);
  1102.  
  1103.         default :
  1104.  
  1105.           break;
  1106.       }
  1107.  
  1108.       break;
  1109.  
  1110.     case WM_CLOSE :
  1111.  
  1112.       if(IsWindowVisible(hWnd))
  1113.       {
  1114.         ShowWindow(hWnd, SW_HIDE);
  1115.       }
  1116.       else
  1117.       {
  1118.         ShowWindow(hWnd, SW_SHOWNORMAL);
  1119.       }
  1120.       return(0L);
  1121.  
  1122.     case WM_ACTIVATE :
  1123.  
  1124.       hDlgActive = (wParam == NULL) ? NULL : hWnd;
  1125.       break;
  1126.  
  1127.     default :
  1128.       
  1129.       break;
  1130.   }
  1131.  
  1132.   return(DefDlgProc(hWnd, wMsg, wParam, lParam));
  1133. }
  1134.  
  1135.  
  1136. /*****************************************************************************
  1137.  
  1138.     FUNCTION: UpdatePos
  1139.  
  1140.     PURPOSE : Updates cursor information in dialog
  1141.  
  1142. *****************************************************************************/
  1143.  
  1144. VOID PASCAL UpdatePos(VOID)
  1145. {
  1146.   POINT  Point;
  1147.   POINT  Client;
  1148.  
  1149.   if(hWndTarget == NULL)
  1150.   {
  1151.     return;
  1152.   }
  1153.  
  1154.   //
  1155.   // Get some cursor information
  1156.   //
  1157.  
  1158.   GetCursorPos((LPPOINT) &Point);
  1159.  
  1160.   if(ShowScreenCoord == FALSE)
  1161.   {
  1162.     LONG Units = GetDialogBaseUnits();
  1163.     WORD Xamt = LOWORD(Units);
  1164.     WORD Yamt = HIWORD(Units);
  1165.  
  1166.     Point.x  = (Point.x * 4 ) / Xamt;
  1167.     Point.y  = (Point.y * 4 ) / Yamt;
  1168.   }
  1169.  
  1170.   if((hWndTarget != NULL) && (GetParent(hWndTarget) != NULL))
  1171.   {
  1172.     Client.x = Point.x;
  1173.     Client.y = Point.y;
  1174.  
  1175.     ScreenToClient(hWndTarget, (LPPOINT) &Client);
  1176.   }
  1177.   else
  1178.   {
  1179.     Client.x = 0;
  1180.     Client.y = 0;
  1181.   }
  1182.  
  1183.   if(ShowHex)
  1184.   {
  1185.     wsprintf
  1186.     (
  1187.       (LPSTR) Text,
  1188.       "Cursor = (0x%04x, 0x%04x), (0x%04x, 0x%04x)",
  1189.       Point.x,
  1190.       Point.y,
  1191.       Client.x,
  1192.       Client.y
  1193.     );
  1194.   }
  1195.   else
  1196.   {
  1197.     wsprintf
  1198.     (
  1199.       (LPSTR) Text,
  1200.       "Cursor = (%d, %d), (%d, %d)",
  1201.       Point.x,
  1202.       Point.y,
  1203.       Client.x,
  1204.       Client.y
  1205.     );
  1206.   }
  1207.  
  1208.   SetDlgItemText(hDlgPropView, IDC_POS, (LPSTR) Text);
  1209. }
  1210.  
  1211.  
  1212. /*****************************************************************************
  1213.  
  1214.     FUNCTION: ExamineWindow
  1215.  
  1216.     PURPOSE : Shows info on selected window (ie. children, parent, properties)
  1217.  
  1218. *****************************************************************************/
  1219.  
  1220. VOID PASCAL ExamineWindow(HWND hWnd)
  1221. {
  1222.   #define NUMCLASSSTYLES  11
  1223.   #define NUMWNDSTYLES  29
  1224.  
  1225.   HWND  hWndParent;
  1226.   BYTE  ModuleFileName[30];
  1227.   BYTE  ClassName[30];
  1228.   BYTE  hWndText[7];
  1229.   RECT  Rect;
  1230.   int    i;
  1231.   HANDLE  hInst;
  1232.  
  1233.   LONG  WndStyle;
  1234.   WORD  ClassStyle;
  1235.   WORD  WndExtraData;
  1236.   WORD  ClsExtraData;
  1237.  
  1238.   static struct
  1239.   {
  1240.     WORD  Style;
  1241.     LPSTR  Text;
  1242.   }
  1243.   ClassStyles[NUMCLASSSTYLES] =
  1244.   {
  1245.     {CS_BYTEALIGNCLIENT,  "CS_BYTEALIGNCLIENT"},
  1246.     {CS_BYTEALIGNWINDOW,  "CS_BYTEALIGNWINDOW"},
  1247.     {CS_CLASSDC,      "CS_CLASSDC"},
  1248.     {CS_DBLCLKS,      "CS_DBLCLKS"},
  1249.     {CS_GLOBALCLASS,    "CS_GLOBALCLASS"},
  1250.     {CS_HREDRAW,      "CS_HREDRAW"},
  1251.     {CS_NOCLOSE,      "CS_NOCLOSE"},
  1252.     {CS_OWNDC,        "CS_OWNDC"},
  1253.     {CS_PARENTDC,      "CS_PARENTDC"},
  1254.     {CS_SAVEBITS,      "CS_SAVEBITS"},
  1255.     {CS_VREDRAW,      "CS_VREDRAW"}
  1256.   };
  1257.  
  1258.   static struct
  1259.   {
  1260.     LONG  Style;
  1261.     LPSTR  Text;
  1262.   }
  1263.   WndStyles[NUMWNDSTYLES] =
  1264.   {
  1265.     {WS_POPUP,        "WS_POPUP"},
  1266.     {WS_OVERLAPPED,      "WS_OVERLAPPED"},
  1267.     {WS_CHILD,        "WS_CHILD"},
  1268.     {WS_MINIMIZE,      "WS_MINIMIZE"},
  1269.     {WS_VISIBLE,      "WS_VISIBLE"},
  1270.     {WS_DISABLED,      "WS_DISABLED"},
  1271.     {WS_CLIPSIBLINGS,    "WS_CLIPSIBLINGS"},
  1272.     {WS_CLIPCHILDREN,    "WS_CLIPCHILDREN"},
  1273.     {WS_MAXIMIZE,      "WS_MAXIMIZE"},
  1274.     {WS_CAPTION,      "WS_CAPTION"},
  1275.     {WS_BORDER,        "WS_BORDER"},
  1276.     {WS_DLGFRAME,      "WS_DLGFRAME"},
  1277.     {WS_VSCROLL,      "WS_VSCROLL"},
  1278.     {WS_HSCROLL,      "WS_HSCROLL"},
  1279.     {WS_SYSMENU,      "WS_SYSMENU"},
  1280.     {WS_THICKFRAME,      "WS_THICKFRAME"},
  1281.     {WS_GROUP,        "WS_GROUP"},
  1282.     {WS_TABSTOP,      "WS_TABSTOP"},
  1283.     {WS_MINIMIZEBOX,    "WS_MINIMIZEBOX"},
  1284.     {WS_MAXIMIZEBOX,    "WS_MAXIMIZEBOX"},
  1285.     {WS_EX_DLGMODALFRAME,  "WS_EX_DLGMODALFRAME"},
  1286.     {WS_EX_NOPARENTNOTIFY,  "WS_EX_NOPARENTNOTIFY"}
  1287.   };
  1288.  
  1289.   //
  1290.   // Check for NULL hWnd
  1291.   //
  1292.  
  1293.   if((hWnd == NULL) || !IsWindow(hWnd))
  1294.   {
  1295.     return;
  1296.   }
  1297.  
  1298.   //
  1299.   // We have a new target window
  1300.   //
  1301.  
  1302.   hWndTarget = hWnd;
  1303.  
  1304.   //
  1305.   // DRAW ICONS
  1306.   //
  1307.  
  1308.   DrawIcons();
  1309.  
  1310.   //
  1311.   // Turn on outline of target window
  1312.   //
  1313.  
  1314.   OutlineWindow(hWndTarget);
  1315.  
  1316.   //
  1317.   // Update the hWnd in the SendMsg dialog
  1318.   //
  1319.  
  1320.   if(ShowHex)
  1321.   {
  1322.     wsprintf(hWndText, "0x%04x", hWndTarget);
  1323.   }  
  1324.   else
  1325.   {
  1326.     wsprintf(hWndText, "%d", hWndTarget);
  1327.   }  
  1328.  
  1329.   SetDlgItemText(hDlgSendMsg, IDC_HWNDTOSEND, (LPSTR) hWndText);
  1330.  
  1331.   //
  1332.   // Display different window stats
  1333.   //
  1334.  
  1335.   GetClassName(hWnd, (LPSTR) ClassName, sizeof(ClassName));
  1336.  
  1337.   if(ShowHex)
  1338.   {
  1339.     wsprintf
  1340.     (
  1341.       (LPSTR) Text,
  1342.       "= 0x%04x (0x%04x), %s",
  1343.       hWnd,
  1344.       GetDlgCtrlID(hWnd),
  1345.       (LPSTR) ClassName
  1346.     );
  1347.   }
  1348.   else
  1349.   {
  1350.     wsprintf
  1351.     (
  1352.       (LPSTR) Text,
  1353.       "= %d (%d), %s",
  1354.       hWnd,
  1355.       GetDlgCtrlID(hWnd),
  1356.       (LPSTR) ClassName
  1357.     );
  1358.   }
  1359.  
  1360.   SetDlgItemText(hDlgPropView, IDC_HWND, (LPSTR) Text);
  1361.  
  1362.   if(!GetWindowText(hWnd, (LPSTR) Text, sizeof(Text)))
  1363.   {
  1364.     Text[0] = '\0';
  1365.   }
  1366.  
  1367.   SetDlgItemText(hDlgPropView, IDC_CAPTION, (LPSTR) Text);
  1368.  
  1369.   if((hWndParent = GetParent(hWnd)) != NULL)
  1370.   {
  1371.     GetClassName(hWndParent, (LPSTR) ClassName, sizeof(ClassName));
  1372.  
  1373.     if(ShowHex)
  1374.     {
  1375.       wsprintf
  1376.       (
  1377.         (LPSTR) Text,
  1378.         "= 0x%04x (0x%04x), %s",
  1379.         hWndParent,
  1380.         GetDlgCtrlID(hWndParent),
  1381.         (LPSTR) ClassName
  1382.       );
  1383.     }
  1384.     else
  1385.     {
  1386.       wsprintf
  1387.       (
  1388.         (LPSTR) Text,
  1389.         "= %d (%d), %s",
  1390.         hWndParent,
  1391.         GetDlgCtrlID(hWndParent),
  1392.         (LPSTR) ClassName
  1393.       );
  1394.     }
  1395.  
  1396.     SetDlgItemText(hDlgPropView, IDC_HWNDPARENT, (LPSTR) Text);
  1397.  
  1398.     if(!GetWindowText(hWndParent, (LPSTR) Text, sizeof(Text)))
  1399.     {
  1400.       Text[0] = '\0';
  1401.     }
  1402.  
  1403.     SetDlgItemText(hDlgPropView, IDC_PARENTCAPTION, (LPSTR) Text);
  1404.   }
  1405.   else
  1406.   {
  1407.     SetDlgItemText(hDlgPropView, IDC_HWNDPARENT, (LPSTR) "=");
  1408.     SetDlgItemText(hDlgPropView, IDC_PARENTCAPTION, (LPSTR) "");
  1409.   }
  1410.  
  1411.   //
  1412.   // Get and display INSTANCE information
  1413.   //
  1414.  
  1415.   hInst = GetWindowWord(hWnd, GWW_HINSTANCE);
  1416.   GetModuleFileName(hInst, (LPSTR) ModuleFileName, sizeof(ModuleFileName));
  1417.  
  1418.   if(ShowHex)
  1419.   {
  1420.     wsprintf
  1421.     (
  1422.       (LPSTR) Text,
  1423.       "hInst = 0x%04x, %s",
  1424.       hInst,
  1425.       (LPSTR) ModuleFileName
  1426.     );
  1427.   }
  1428.   else
  1429.   {
  1430.     wsprintf
  1431.     (
  1432.       (LPSTR) Text,
  1433.       "hInst = %d, %s",
  1434.       hInst,
  1435.       (LPSTR) ModuleFileName
  1436.     );
  1437.   }
  1438.   SetDlgItemText(hDlgPropView, IDC_HINST, (LPSTR) Text);
  1439.  
  1440.   //
  1441.   // Get & display RECT of window
  1442.   //
  1443.  
  1444.   GetWindowRect(hWnd, (LPRECT) &Rect);
  1445.  
  1446.   if(ShowScreenCoord == FALSE)
  1447.   {
  1448.     LONG Units = GetDialogBaseUnits();
  1449.     WORD Xamt = LOWORD(Units);
  1450.     WORD Yamt = HIWORD(Units);
  1451.  
  1452.     Rect.left  = (Rect.left * Xamt) / 4;
  1453.     Rect.right  = (Rect.right * Xamt) / 4;
  1454.     Rect.top  = (Rect.top * Yamt) / 4;
  1455.     Rect.bottom  = (Rect.bottom * Yamt) / 4;
  1456.   }
  1457.  
  1458.   if(ShowHex)
  1459.   {
  1460.     wsprintf
  1461.     (
  1462.       (LPSTR) Text,
  1463.       "Rect = (0x%04x, 0x%04x)-(0x%04x, 0x%04x)",
  1464.       Rect.left,
  1465.       Rect.top,
  1466.       Rect.right,
  1467.       Rect.bottom
  1468.     );
  1469.   }
  1470.   else
  1471.   {
  1472.     wsprintf
  1473.     (
  1474.       (LPSTR) Text,
  1475.       "Rect = (%d, %d)-(%d, %d)",
  1476.       Rect.left,
  1477.       Rect.top,
  1478.       Rect.right,
  1479.       Rect.bottom
  1480.     );
  1481.   }
  1482.   SetDlgItemText(hDlgPropView, IDC_RECT, (LPSTR) Text);
  1483.  
  1484.   //
  1485.   // Get & display CHILDREN & PROPERTY information
  1486.   //
  1487.  
  1488.   SendDlgItemMessage(hDlgChildren, IDC_LISTBOX, WM_SETREDRAW, 0, 0L);
  1489.   SendDlgItemMessage(hDlgProperties, IDC_LISTBOX, WM_SETREDRAW, 0, 0L);
  1490.  
  1491.   SendDlgItemMessage(hDlgProperties, IDC_LISTBOX, LB_RESETCONTENT, 0, 0L);
  1492.   SendDlgItemMessage(hDlgChildren, IDC_LISTBOX, LB_RESETCONTENT, 0, 0L);
  1493.  
  1494.   EnumChildWindows(hWndTarget, lpEnumChildrenProc, NULL);
  1495.  
  1496.   if
  1497.   (
  1498.     !(i = (int) SendDlgItemMessage
  1499.     (
  1500.       hDlgChildren,
  1501.       IDC_LISTBOX,
  1502.       LB_GETCOUNT,
  1503.       0,
  1504.       0L
  1505.     ))
  1506.   )
  1507.   {
  1508.     SetWindowText(hDlgChildren, "No children");
  1509.   }
  1510.   else
  1511.   {
  1512.     if(i == 1)
  1513.     {
  1514.       SetWindowText(hDlgChildren, "One child");
  1515.     }
  1516.     else
  1517.     {
  1518.       wsprintf(Text, "%d Children", i);
  1519.       SetWindowText(hDlgChildren, Text);
  1520.     }
  1521.   }
  1522.  
  1523.   if(GetParent(hWndTarget))
  1524.   {
  1525.     SendDlgItemMessage
  1526.     (
  1527.       hDlgChildren,
  1528.       IDC_LISTBOX,
  1529.       LB_ADDSTRING,
  1530.       0,
  1531.       (LONG) (LPSTR) "\"..\" (parent)"
  1532.     );
  1533.   }
  1534.  
  1535.   EnumProps(hWndTarget, lpEnumWindowPropsProc);
  1536.  
  1537.   if
  1538.   (
  1539.     !(i = (int) SendDlgItemMessage
  1540.     (
  1541.       hDlgProperties,
  1542.       IDC_LISTBOX,
  1543.       LB_GETCOUNT,
  1544.       0,
  1545.       0L
  1546.     ))
  1547.   )
  1548.   {
  1549.     SetWindowText(hDlgProperties, "No properties");
  1550.   }
  1551.   else
  1552.   {
  1553.     if(i == 1)
  1554.     {
  1555.       SetWindowText(hDlgProperties, "One property");
  1556.     }
  1557.     else
  1558.     {
  1559.       wsprintf(Text, "%d Properties", i);
  1560.       SetWindowText(hDlgProperties, Text);
  1561.     }
  1562.   }
  1563.  
  1564.   //
  1565.   // Now, turn redrawing for both listbox windows back on, invalidating their
  1566.   // areas, and sending a WM_PAINT.
  1567.   //
  1568.  
  1569.   SendDlgItemMessage(hDlgChildren, IDC_LISTBOX, WM_SETREDRAW, 1, 0L);
  1570.   SendDlgItemMessage(hDlgProperties, IDC_LISTBOX, WM_SETREDRAW, 1, 0L);
  1571.  
  1572.   InvalidateRect(GetDlgItem(hDlgChildren, IDC_LISTBOX), NULL, TRUE);
  1573.   InvalidateRect(GetDlgItem(hDlgProperties, IDC_LISTBOX), NULL, TRUE);
  1574.  
  1575.   UpdateWindow(GetDlgItem(hDlgChildren, IDC_LISTBOX));
  1576.   UpdateWindow(GetDlgItem(hDlgProperties, IDC_LISTBOX));
  1577.  
  1578.   //
  1579.   // Update the Data window
  1580.   //
  1581.  
  1582.   SendDlgItemMessage(hDlgExtraData, IDC_WNDLIST, WM_SETREDRAW, 0, 0L);
  1583.   SendDlgItemMessage(hDlgExtraData, IDC_CLSLIST, WM_SETREDRAW, 0, 0L);
  1584.   SendDlgItemMessage(hDlgExtraData, IDC_WNDLIST, LB_RESETCONTENT, 0, 0L);
  1585.   SendDlgItemMessage(hDlgExtraData, IDC_CLSLIST, LB_RESETCONTENT, 0, 0L);
  1586.  
  1587.   WndExtraData = GetClassWord(hWndTarget, GCW_CBWNDEXTRA);
  1588.   ClsExtraData = GetClassWord(hWndTarget, GCW_CBCLSEXTRA);
  1589.  
  1590.   if(ShowHex)
  1591.   {
  1592.     wsprintf
  1593.     (
  1594.       (LPSTR) Text,
  1595.       "Window = 0x%04x bytes",
  1596.       WndExtraData
  1597.     );
  1598.   }
  1599.   else
  1600.   {
  1601.     wsprintf
  1602.     (
  1603.       (LPSTR) Text,
  1604.       "Window = %d bytes",
  1605.       WndExtraData
  1606.     );
  1607.   }
  1608.   SetDlgItemText(hDlgExtraData, IDC_WNDTEXT, (LPSTR) Text);
  1609.  
  1610.   for(i = 0; i < (int) WndExtraData; i += 2)
  1611.   {
  1612.     BYTE Byte[5];
  1613.  
  1614.     if(ShowHex)
  1615.     {
  1616.       wsprintf(Byte, "0x%04x", GetWindowWord(hWndTarget, i));
  1617.     }
  1618.     else
  1619.     {
  1620.       wsprintf(Byte, "%d", GetWindowWord(hWndTarget, i));
  1621.     }
  1622.  
  1623.     SendDlgItemMessage
  1624.     (
  1625.       hDlgExtraData,
  1626.       IDC_WNDLIST,
  1627.       LB_ADDSTRING,
  1628.       0,
  1629.       (LONG) (LPSTR) Byte
  1630.     );
  1631.   }
  1632.  
  1633.   //
  1634.   // Reset, and then fill the class bytes listbox
  1635.   //
  1636.  
  1637.   if(ShowHex)
  1638.   {
  1639.     wsprintf
  1640.     (
  1641.       (LPSTR) Text,
  1642.       "Class = 0x%04x bytes",
  1643.       ClsExtraData
  1644.     );
  1645.   }
  1646.   else
  1647.   {
  1648.     wsprintf
  1649.     (
  1650.       (LPSTR) Text,
  1651.       "Class = %d bytes",
  1652.       ClsExtraData
  1653.     );
  1654.   }
  1655.   SetDlgItemText(hDlgExtraData, IDC_CLSTEXT, (LPSTR) Text);
  1656.  
  1657.   for(i = 0; i < (int) ClsExtraData; i += 2)
  1658.   {
  1659.     BYTE Byte[7];
  1660.  
  1661.     if(ShowHex)
  1662.     {
  1663.       wsprintf(Byte, "0x%04x", GetClassWord(hWndTarget, i));
  1664.     }
  1665.     else
  1666.     {
  1667.       wsprintf(Byte, "%d", GetClassWord(hWndTarget, i));
  1668.     }
  1669.  
  1670.     SendDlgItemMessage
  1671.     (
  1672.       hDlgExtraData,
  1673.       IDC_CLSLIST,
  1674.       LB_ADDSTRING,
  1675.       0,
  1676.       (LONG) (LPSTR) Byte
  1677.     );
  1678.   }
  1679.  
  1680.   SendDlgItemMessage(hDlgExtraData, IDC_CLSLIST, WM_SETREDRAW, 1, 0L);
  1681.   SendDlgItemMessage(hDlgExtraData, IDC_WNDLIST, WM_SETREDRAW, 1, 0L);
  1682.   InvalidateRect(GetDlgItem(hDlgExtraData, IDC_CLSLIST), NULL, TRUE);
  1683.   InvalidateRect(GetDlgItem(hDlgExtraData, IDC_WNDLIST), NULL, TRUE);
  1684.   UpdateWindow(GetDlgItem(hDlgExtraData, IDC_CLSLIST));
  1685.   UpdateWindow(GetDlgItem(hDlgExtraData, IDC_WNDLIST));
  1686.  
  1687.   //
  1688.   // Update the Styles window
  1689.   //
  1690.  
  1691.   SendDlgItemMessage(hDlgStyles, IDC_WNDLIST, WM_SETREDRAW, 0, 0L);
  1692.   SendDlgItemMessage(hDlgStyles, IDC_CLSLIST, WM_SETREDRAW, 0, 0L);
  1693.   SendDlgItemMessage(hDlgStyles, IDC_WNDLIST, LB_RESETCONTENT, 0, 0L);
  1694.   SendDlgItemMessage(hDlgStyles, IDC_CLSLIST, LB_RESETCONTENT, 0, 0L);
  1695.  
  1696.   WndStyle  = GetWindowLong(hWndTarget, GWL_STYLE);
  1697.   ClassStyle  = GetClassWord(hWndTarget, GCW_STYLE);
  1698.  
  1699.   if(ShowHex)
  1700.   {
  1701.     wsprintf
  1702.     (
  1703.       (LPSTR) Text,
  1704.       "Wnd Style = 0x%08lx",
  1705.       WndStyle
  1706.     );
  1707.   }
  1708.   else
  1709.   {
  1710.     wsprintf
  1711.     (
  1712.       (LPSTR) Text,
  1713.       "Wnd Style = %ld",
  1714.       WndStyle
  1715.     );
  1716.   }
  1717.   SetDlgItemText(hDlgStyles, IDC_WNDTEXT, (LPSTR) Text);
  1718.  
  1719.   //
  1720.   // Check to see if the window is a popup. If so, don't throw in
  1721.   // WS_OVERLAPPED attribute.
  1722.   //
  1723.  
  1724.   if(WndStyle & WndStyles[0].Style)
  1725.   {
  1726.     SendDlgItemMessage
  1727.     (
  1728.       hDlgStyles,
  1729.       IDC_WNDLIST,
  1730.       LB_ADDSTRING,
  1731.       0,
  1732.       (LONG) (LPSTR) WndStyles[1].Text
  1733.     );
  1734.   }
  1735.   else
  1736.   {
  1737.     if(WndStyle & WndStyles[1].Style)
  1738.     {
  1739.       SendDlgItemMessage
  1740.       (
  1741.         hDlgStyles,
  1742.         IDC_WNDLIST,
  1743.         LB_ADDSTRING,
  1744.         0,
  1745.         (LONG) (LPSTR) WndStyles[0].Text
  1746.       );
  1747.     }
  1748.   }
  1749.  
  1750.   for(i = 2; i < NUMWNDSTYLES; ++i)
  1751.   {
  1752.     if(WndStyle & WndStyles[i].Style)
  1753.     {
  1754.       SendDlgItemMessage
  1755.       (
  1756.         hDlgStyles,
  1757.         IDC_WNDLIST,
  1758.         LB_ADDSTRING,
  1759.         0,
  1760.         (LONG) (LPSTR) WndStyles[i].Text
  1761.       );
  1762.     }
  1763.   }
  1764.  
  1765.   //
  1766.   // Reset, and then fill the class styles combo box
  1767.   //
  1768.  
  1769.   if(ShowHex)
  1770.   {
  1771.     wsprintf
  1772.     (
  1773.       (LPSTR) Text,
  1774.       "Class Style = 0x%04x",
  1775.       ClassStyle
  1776.     );
  1777.   }
  1778.   else
  1779.   {
  1780.     wsprintf
  1781.     (
  1782.       (LPSTR) Text,
  1783.       "Class Style = %d",
  1784.       ClassStyle
  1785.     );
  1786.   }
  1787.   SetDlgItemText(hDlgStyles, IDC_CLSTEXT, (LPSTR) Text);
  1788.  
  1789.   for(i = 0; i < NUMCLASSSTYLES; ++i)
  1790.   {
  1791.     if(ClassStyle & ClassStyles[i].Style)
  1792.     {
  1793.       SendDlgItemMessage
  1794.       (
  1795.         hDlgStyles,
  1796.         IDC_CLSLIST,
  1797.         LB_ADDSTRING,
  1798.         0,
  1799.         (LONG) (LPSTR) ClassStyles[i].Text
  1800.       );
  1801.     }
  1802.   }
  1803.  
  1804.   //
  1805.   // Turn off outline of target window
  1806.   //
  1807.  
  1808.   OutlineWindow(hWndTarget);
  1809.  
  1810.   //
  1811.   // Turn redrawing back on and repaint all listboxes
  1812.   //
  1813.  
  1814.   SendDlgItemMessage(hDlgStyles, IDC_WNDLIST, WM_SETREDRAW, 1, 0L);
  1815.   SendDlgItemMessage(hDlgStyles, IDC_CLSLIST, WM_SETREDRAW, 1, 0L);
  1816.   InvalidateRect(GetDlgItem(hDlgStyles, IDC_WNDLIST), NULL, TRUE);
  1817.   InvalidateRect(GetDlgItem(hDlgStyles, IDC_CLSLIST), NULL, TRUE);
  1818.   UpdateWindow(GetDlgItem(hDlgStyles, IDC_WNDLIST));
  1819.   UpdateWindow(GetDlgItem(hDlgStyles, IDC_CLSLIST));
  1820. }
  1821.  
  1822.  
  1823. /*****************************************************************************
  1824.  
  1825.     FUNCTION: EnumWindowPropsProc
  1826.  
  1827.     PURPOSE : Enumerates properties for window under mouse
  1828.  
  1829. *****************************************************************************/
  1830.  
  1831. int FAR PASCAL EnumWindowPropsProc(HWND hWnd, LPSTR lpString, HANDLE hData)
  1832. {
  1833.   //
  1834.   // Check the passed property name to see if it's a string or an atom
  1835.   //
  1836.  
  1837.   if(HIWORD(lpString))
  1838.   {
  1839.     if(ShowHex)
  1840.     {
  1841.       wsprintf(Text, "%s\t= 0x%04x", (LPSTR) lpString, hData);
  1842.     }
  1843.     else
  1844.     {
  1845.       wsprintf(Text, "%s\t= %d", (LPSTR) lpString, hData);
  1846.     }
  1847.   }
  1848.   else
  1849.   {
  1850.     if(ShowHex)
  1851.     {
  1852.       wsprintf(Text, "0x%04x, 0x%04x", LOWORD((DWORD) lpString), hData);
  1853.     }
  1854.     else
  1855.     {
  1856.       wsprintf(Text, "%d, %d", LOWORD((DWORD) lpString), hData);
  1857.     }
  1858.   }
  1859.  
  1860.   SendDlgItemMessage
  1861.   (
  1862.     hDlgProperties,
  1863.     IDC_LISTBOX,
  1864.     LB_ADDSTRING,
  1865.     0,
  1866.     (LONG) (LPSTR) Text
  1867.   );
  1868.  
  1869.   return(1);
  1870. }
  1871.  
  1872.  
  1873. /*****************************************************************************
  1874.  
  1875.     FUNCTION: DrawIcons
  1876.  
  1877.     PURPOSE : Draws the target and parent class icons
  1878.  
  1879. *****************************************************************************/
  1880.  
  1881. VOID PASCAL DrawIcons(VOID)
  1882. {
  1883.   HWND  hWndParent;
  1884.   HDC    hDC;
  1885.   HFONT  hFont;
  1886.   HICON  hIcon;
  1887.   BYTE  ClassName[30];
  1888.  
  1889. #ifdef MEWEL
  1890.   /*
  1891.     We have character mode icons in MEWEL, but they really won't look
  1892.     too good in this relatively small dialog box.
  1893.   */
  1894.   return;
  1895. #endif
  1896.  
  1897.   if(hWndTarget == NULL)
  1898.   {
  1899.     return;
  1900.   }
  1901.  
  1902.   //
  1903.   // Setup small prop helv font for icon titles
  1904.   //
  1905.  
  1906.   hFont = CreateFont
  1907.   (
  1908.     12, 0,
  1909.     0, 0,
  1910.     FW_NORMAL,
  1911.     FALSE,
  1912.     FALSE,
  1913.     FALSE,
  1914.     ANSI_CHARSET,
  1915.     OUT_DEFAULT_PRECIS,
  1916.     CLIP_DEFAULT_PRECIS,
  1917.     DEFAULT_QUALITY,
  1918.     VARIABLE_PITCH | FF_SWISS,
  1919.     "Helv"
  1920.   );
  1921.  
  1922.   //
  1923.   // Get window class name & draw icon
  1924.   //
  1925.  
  1926.   if(!GetClassName(hWndTarget, (LPSTR) ClassName, sizeof(ClassName)))
  1927.   {
  1928.     ClassName[0] = '\0';
  1929.   }
  1930.  
  1931.   if((hIcon = GetClassWord(hWndTarget, GCW_HICON)) == NULL)
  1932.   {
  1933.     if(!lstrcmpi((LPSTR) ClassName, "listbox"))
  1934.     {
  1935.       hIcon = LoadIcon(hInstPropView, "listbox");
  1936.     }
  1937.     else
  1938.     {
  1939.       if(!lstrcmpi((LPSTR) ClassName, "combobox"))
  1940.       {
  1941.         hIcon = LoadIcon(hInstPropView, "combobox");
  1942.       }
  1943.       else
  1944.       {
  1945.         if(!lstrcmpi((LPSTR) ClassName, "button"))
  1946.         {
  1947.           hIcon = LoadIcon(hInstPropView, "button");
  1948.         }
  1949.         else
  1950.         {
  1951.           if(!lstrcmpi((LPSTR) ClassName, "edit") ||
  1952.             !lstrcmpi((LPSTR) ClassName, "static"))
  1953.           {
  1954.             hIcon = LoadIcon(hInstPropView, "editcontrol");
  1955.           }
  1956.         }
  1957.       }
  1958.     }
  1959.   }
  1960.  
  1961.   //
  1962.   // Get DC, draw icon, and release DC
  1963.   //
  1964.  
  1965.   hDC = GetDC(GetDlgItem(hDlgPropView, IDC_HWNDICON));
  1966.  
  1967.   if((hIcon == NULL) && IsIconic(hWndTarget) && IsWindowVisible(hWndTarget))
  1968.   {
  1969.     HDC hDCTarget = GetWindowDC(hWndTarget);
  1970.     BitBlt(hDC, 0, 0, 36, 36, hDCTarget, 0, 0, SRCCOPY);
  1971.     ReleaseDC(hWndTarget, hDCTarget);
  1972.   }
  1973.   else
  1974.   {
  1975.     BitBlt(hDC, 0, 0, 36, 36, hDC, 0, 0, WHITENESS);
  1976.     DrawIcon(hDC, 0, 0, hIcon);
  1977.   }
  1978.  
  1979.   ReleaseDC(GetDlgItem(hDlgPropView, IDC_HWNDICON), hDC);
  1980.  
  1981.   if((hWndParent = GetParent(hWndTarget)) != NULL)
  1982.   {
  1983.     HICON hIcon;
  1984.  
  1985.     //
  1986.     // Get DC, draw icon, and release DC
  1987.     //
  1988.  
  1989.     hDC = GetDC(GetDlgItem(hDlgPropView, IDC_PARENTICON));
  1990.  
  1991.     if
  1992.     (
  1993.       ((hIcon = GetClassWord(hWndParent, GCW_HICON)) == NULL) &&
  1994.       IsIconic(hWndParent) && IsWindowVisible(hWndTarget)
  1995.     )
  1996.     {
  1997.       HDC hDCTarget = GetWindowDC(hWndParent);
  1998.       BitBlt(hDC, 0, 0, 36, 36, hDCTarget, 0, 0, SRCCOPY);
  1999.       ReleaseDC(hWndParent, hDCTarget);
  2000.     }
  2001.     else
  2002.     {
  2003.       BitBlt(hDC, 0, 0, 36, 36, hDC, 0, 0, WHITENESS);
  2004.       DrawIcon(hDC, 0, 0, hIcon);
  2005.     }
  2006.  
  2007.     ReleaseDC(GetDlgItem(hDlgPropView, IDC_PARENTICON), hDC);
  2008.   }
  2009.   else
  2010.   {
  2011.     //
  2012.     // Get DC, draw icon, and release DC
  2013.     //
  2014.  
  2015.     hDC = GetDC(GetDlgItem(hDlgPropView, IDC_PARENTICON));
  2016.     BitBlt(hDC, 0, 0, 36, 36, hDC, 0, 0, WHITENESS);
  2017.     ReleaseDC(GetDlgItem(hDlgPropView, IDC_PARENTICON), hDC);
  2018.   }
  2019.  
  2020.   //
  2021.   // Do usual cleanup
  2022.   //
  2023.  
  2024.   DeleteObject(hFont);
  2025. }
  2026.  
  2027.  
  2028. /*****************************************************************************
  2029.  
  2030.     FUNCTION: EnumChildrenProc
  2031.  
  2032.     PURPOSE : Enumerates children of window under mouse
  2033.  
  2034. *****************************************************************************/
  2035.  
  2036. int FAR PASCAL EnumChildrenProc(HWND hWnd, DWORD lParam)
  2037. {
  2038.   BYTE Text[100];
  2039.   BYTE Caption[100];
  2040.   BYTE ClassName[30];
  2041.  
  2042.   //
  2043.   // Get the child window's caption and class name
  2044.   //
  2045.  
  2046.   GetWindowText(hWnd, (LPSTR) Caption, sizeof(Caption));
  2047.   GetClassName(hWnd, (LPSTR) ClassName, sizeof(ClassName));
  2048.  
  2049.   //
  2050.   // Format and add the entry to the child list box
  2051.   //
  2052.  
  2053.   if(Caption[0] != '\0')
  2054.   {
  2055.     if(ShowHex)
  2056.     {
  2057.       wsprintf
  2058.       (
  2059.         (LPSTR) Text,
  2060.         "%s\t0x%04x\t0x%04x\t\"%s\"",
  2061.         (LPSTR) ClassName,
  2062.         GetDlgCtrlID(hWnd),
  2063.         hWnd,
  2064.         (LPSTR) Caption
  2065.       );
  2066.     }
  2067.     else
  2068.     {
  2069.       wsprintf
  2070.       (
  2071.         (LPSTR) Text,
  2072.         "%s\t%d\t%d\t\"%s\"",
  2073.         (LPSTR) ClassName,
  2074.         GetDlgCtrlID(hWnd),
  2075.         hWnd,
  2076.         (LPSTR) Caption
  2077.       );
  2078.     }
  2079.   }
  2080.   else
  2081.   {
  2082.     if(ShowHex)
  2083.     {
  2084.       wsprintf
  2085.       (
  2086.         (LPSTR) Text,
  2087.         "%s\t0x%04x\t0x%04x",
  2088.         (LPSTR) ClassName,
  2089.         GetDlgCtrlID(hWnd),
  2090.         hWnd
  2091.       );
  2092.     }
  2093.     else
  2094.     {
  2095.       wsprintf
  2096.       (
  2097.         (LPSTR) Text,
  2098.         "%s\t%d\t%d",
  2099.         (LPSTR) ClassName,
  2100.         GetDlgCtrlID(hWnd),
  2101.         hWnd
  2102.       );
  2103.     }
  2104.   }
  2105.  
  2106.   SendDlgItemMessage
  2107.   (
  2108.     hDlgChildren,
  2109.     IDC_LISTBOX,
  2110.     LB_ADDSTRING,
  2111.     0,
  2112.     (LONG) (LPSTR) Text
  2113.   );
  2114.  
  2115.   return(1);
  2116. }
  2117.  
  2118.  
  2119. /*****************************************************************************
  2120.  
  2121.     FUNCTION: About
  2122.  
  2123.     PURPOSE : Processes messages for About box
  2124.  
  2125. *****************************************************************************/
  2126.  
  2127. BOOL FAR PASCAL About(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam)
  2128. {
  2129.   switch(wMsg)
  2130.   {
  2131.     case WM_INITDIALOG :
  2132.  
  2133.       return(TRUE);
  2134.  
  2135.     case WM_COMMAND    :
  2136.  
  2137.       if(wParam == IDOK || wParam == IDCANCEL)
  2138.       {
  2139.         EndDialog(hWnd, TRUE);
  2140.         return(TRUE);
  2141.       }
  2142.       break;
  2143.  
  2144.     default            :
  2145.  
  2146.       break;
  2147.   }
  2148.   return(FALSE);
  2149. }
  2150.  
  2151.  
  2152. /*****************************************************************************
  2153.  
  2154.     FUNCTION: OutlineWindow
  2155.  
  2156.     PURPOSE : Outlines window with a rectangle
  2157.  
  2158. *****************************************************************************/
  2159.  
  2160. VOID PASCAL OutlineWindow(HWND hWnd)
  2161. {
  2162.   RECT  Rect;
  2163.   HDC    hDC;
  2164.   HPEN  hPen;
  2165.   HPEN  hPenOld;
  2166.   HANDLE  hBrush;
  2167.   HANDLE  hBrushOld;
  2168.   int    OldROP2Mode;
  2169.  
  2170.   //
  2171.   // Check for valid window handle and pen thickness
  2172.   //
  2173.  
  2174.   if(!IsWindow(hWnd))
  2175.   {
  2176.     return;
  2177.   }
  2178.  
  2179.   //
  2180.   // Set up parms to draw rectangle
  2181.   //
  2182.  
  2183.   hBrush  = GetStockObject(NULL_BRUSH);
  2184.   hPen  = CreatePen(PS_SOLID, 6, RGB(0, 0, 0));
  2185.  
  2186.   //
  2187.   // Get DC for window and it's dimensions
  2188.   //
  2189.  
  2190.   hDC = GetWindowDC(hWnd);
  2191.   GetWindowRect(hWnd, (LPRECT) &Rect);
  2192.  
  2193.   //
  2194.   // Set drawing mode parameters
  2195.   //
  2196.  
  2197.   hBrushOld  = SelectObject(hDC, hBrush);
  2198.   hPenOld    = SelectObject(hDC, hPen);
  2199.   OldROP2Mode  = SetROP2(hDC, R2_NOT);
  2200.  
  2201.   //
  2202.   // Draw the rectangle and release the DC
  2203.   //
  2204.  
  2205. #ifdef MEWEL
  2206.   /*
  2207.     Since there is no 'R2_NOT' blitting operation in text mode, we will
  2208.     simulate this by inverting all four sides of the window.
  2209.   */
  2210.   {
  2211.   RECT r;
  2212.   int  cyRect = Rect.bottom - Rect.top + 1;
  2213.   int  cxRect = Rect.right - Rect.left + 1;
  2214.  
  2215.   if (cxRect > 0)
  2216.   {
  2217.     SetRect((LPRECT) &r, 0, 0, cxRect-1, 0);
  2218.     InvertRect(hDC, (LPRECT) &r);
  2219.   }
  2220.  
  2221.   if (cyRect > 1)
  2222.   {
  2223.     SetRect((LPRECT) &r, cxRect-1, 1, cxRect-1, cyRect-2);
  2224.     InvertRect(hDC, (LPRECT) &r);
  2225.   }
  2226.  
  2227.   if (cxRect > 0 && cyRect > 1)
  2228.   {
  2229.     SetRect((LPRECT) &r, 0, cyRect-1, cxRect-1, cyRect-1);
  2230.     InvertRect(hDC, (LPRECT) &r);
  2231.   }
  2232.  
  2233.   if (cyRect > 1)
  2234.   {
  2235.     SetRect((LPRECT) &r, 0, 0, 0, cyRect-2);
  2236.     InvertRect(hDC, (LPRECT) &r);
  2237.   }
  2238.  
  2239.   }
  2240. #else
  2241.   Rectangle(hDC, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top);
  2242. #endif
  2243.  
  2244.   //
  2245.   // Be a good boy and reset the old context attributes
  2246.   //
  2247.  
  2248.   SelectObject(hDC, hBrushOld);
  2249.   SelectObject(hDC, hPenOld);
  2250.   DeleteObject(hPen);
  2251.   SetROP2(hDC, OldROP2Mode);
  2252.  
  2253.   ReleaseDC(hWnd, hDC);
  2254. }
  2255.